package com.example.springbatchdemo.future;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Classname FutureInAction
 * @Description TODO
 * @Date 2020/9/26 17:13
 * @Created by kevin
 */
public class FutureInAction {
    /**
     * 阻塞式调用方法
     *
     * @param callable
     * @param <T>
     * @return
     */
    private static <T> T block( Callable<T> callable ) {
        return callable.action();
    }


    /**
     * 异步调用方法
     *
     * @param callable
     * @param <T>
     * @return
     */
    private static <T> Future<T> invoke( Callable<T> callable ) {

        AtomicReference<T> result = new AtomicReference<>();
        AtomicBoolean finished = new AtomicBoolean(false);


        Thread t = new Thread(() -> {
            T value = callable.action();
            result.set(value);
            finished.set(true);
        });

        t.start();

        Future<T> future = new Future<T>() {


            @Override
            public T get() {
                return result.get();
            }

            @Override
            public boolean isDone() {
                return finished.get();
            }
        };

        return future;

    }

    private interface Future<T> {

        T get();

        boolean isDone();
    }

    private interface Callable<T> {
        T action();
    }


    public static void main( String[] args ) throws InterruptedException {

        /*Future<String> future = invoke(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                return "i am finished";
            } catch (InterruptedException e) {
                return "Error";
            }
        });
        System.out.println(future.get() + "\t" + future.isDone());
        System.out.println(future.get() + "\t" + future.isDone());
        System.out.println(future.get() + "\t" + future.isDone());


        while (!future.isDone()) {

            TimeUnit.MILLISECONDS.sleep(10);

        }
        System.out.println(future.get() + "\t" + future.isDone());
    }*/
        String value = block(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                return "i am finished";
            } catch (InterruptedException e) {
                return "Error";
            }
        });
        System.out.println(value);
    }

}
